export class DListItem {
    public owner: DList | null = null;
    public pre: DListItem | null = null;
    public next: DListItem | null = null;

    removeSelf() {
        if (!this.owner) {
            return;
        }

        if (!this.pre && !this.next) {
            return;
        }

        if (this.owner.head == this) {
            this.owner.head = this.next;
        }
        else if (this.owner.tail == this) {
            this.owner.tail = this.pre;
        }

        if (this.pre) {
            this.pre.next = this.next;
        }

        if (this.next) {
            this.next.pre = this.pre;
        }

        this.owner = null;
        this.pre = null;
        this.next = null;
    }
}

export class DList {
    head: DListItem | null = null;
    tail: DListItem | null = null;

    public add(item: DListItem) {
        if (!item) {
            return;
        }

        if (this.head == null) {
            this.head = this.tail = item;
            item.pre = null;
            item.next = null;
            return;
        }

        if (!this.tail) {
            throw Error('tail can not be nil');
        }

        this.tail.next = item;
        item.pre = this.tail;
        this.tail = item;
    }

    public addHead(item: DListItem) {
        if (!item) {
            return;
        }
        if (this.head == null) {
            this.head = this.tail = item;
            item.pre = null;
            item.next = null;
            return;
        }

        this.head.pre = item;
        item.next = this.head;

        this.head = item;
    }

    public forEach(cb: (v: DListItem) => void) {
        if(!cb){
            return;
        }
        let p = this.head;
        while(p){
            let next = p.next;
            cb(p);
            p = next;
        }
    }
}